<template>
  <scroll-view
    scroll-x
    class="slide-scroll ruler-scroll"
    :enable-flex="true"
    :show-scrollbar="false"
    :style="{ width: screenW + 'px', height: height + 'rpx', alignItems: align }"
    :scroll-left="scrollLeft"
    :scroll-with-animation="true"
    @scroll="slideScroll"
    @touchend="slideMoveEnd"
  >
    <!-- 左侧空白 -->
    <view class="empty-none" :style="{ width: screenW / 2 + 'px' }"></view>

    <!-- 刻度列表 -->
    <block v-for="(s_item, s_index) in list" :key="s_index">
      <!-- 大刻度 -->
      <view
        class="slide-list"
        :style="{
          width: bigItemWidth + 'px',
          margin: `0 ${(cellWidth - bigItemWidth) / 2}px`,
          backgroundColor: selInd === s_index * cells ? selColor : color,
          color: selInd === s_index * cells ? selColor : color,
          height: selInd === s_index * cells ? setUnit(40) : setUnit(bigItemHeight)
        }"
      >
        <view
          class="list-num"
          :style="{
            top: numPos === 'bottom' ? `calc(100% + 5rpx)` : 'auto',
            bottom: numPos === 'top' ? `calc(100% + 5rpx)` : 'auto',
            marginBottom: '20px'
          }"
        >
          {{ s_item }}
        </view>
      </view>

      <!-- 小刻度 -->
      <view
        class="slide-item"
        v-for="(c_item, c_index) in cells - 1"
        :key="c_index"
        :style="{
          width: littleItemWidth + 'px',
          margin: `0 ${(cellWidth - littleItemWidth) / 2}px`,
          backgroundColor:
            selInd === s_index * cells + c_index + 1 ? selColor : color,
          height:
            selInd === s_index * cells + c_index + 1
              ? setUnit(40)
              : setUnit(littleItemHeight)
        }"
      ></view>
    </block>

    <!-- 右侧空白 -->
    <view class="empty-none" :style="{ width: screenW / 2 + 'px' }"></view>
  </scroll-view>
</template>

<script>
export default {
  props: {
    width: { type: Number, default: 100 },
    height: { type: String, default: '' },
    bigItemWidth: { type: Number, default: 2 },
    littleItemWidth: { type: Number, default: 2 },
    cellWidth: { type: Number, default: 20 },
    cells: { type: Number, default: 5 },
    cellNum: { type: Number, default: 1 },
    startNum: { type: Number, default: 0 },
    endNum: { type: Number, default: 20 },
    bgColor: { type: String, default: 'transparent' },
    color: { type: String, default: '#666' },
    selColor: { type: String, default: '#f00' },
    align: { type: String, default: 'center' },
    bigItemHeight: { type: [String, Number], default: 30 },
    littleItemHeight: { type: [String, Number], default: 15 },
    numPos: { type: String, default: 'bottom' },
    value: { type: Number, default: 0 },
  },
  data() {
    return {
      scrollLeft: 0,
      list: [],
      selInd: 0,
      scrollTimer: null,
    };
  },
  computed: {
    screenW() {
      const { width } = this;
      const screenWidth = uni.getSystemInfoSync().screenWidth;
      if (width <= 100 && width > 0) return Math.round((screenWidth * width) / 100);
      if (width > screenWidth || !width) return screenWidth;
      return width;
    },
  },
  mounted() {
    this.initSlide();
    this.$nextTick(() => this.checkValueRange(this.value));
  },
  methods: {
    setUnit(u) {
      return typeof u === 'number' ? `${u}px` : u;
    },

    // ✅ 保留一位小数
    getFixedNum(n) {
      return Number(n.toFixed(1));
    },

    // ✅ 滚动时触发
    slideScroll(e) {
      const scrollL = e.detail.scrollLeft;
      let ind = Math.round(scrollL / this.cellWidth);
      const maxInd = (this.endNum - this.startNum) / this.cellNum;
      if (ind > maxInd) ind = maxInd;
      if (ind !== this.selInd) this.selInd = ind;

      // ✅ 防抖 + 惯性检测
      clearTimeout(this.scrollTimer);
      this.scrollTimer = setTimeout(() => {
        this.slideTo(this.selInd);
        this.setEmitFunc();
      }, 220);
    },

    slideMoveEnd() {
      // 不处理，惯性检测自动完成
    },

    initSlide() {
      const { startNum, endNum, cellNum, cells } = this;
      const listNum = cellNum * cells;
      const len = (endNum - startNum) / listNum;
      this.list = Array.from({ length: len }, (_, i) =>
        this.getFixedNum(startNum + i * listNum)
      );
      this.getSelInd();
    },

    getIntNum(n) {
      return this.getFixedNum(n);
    },

    getSelInd() {
      let value = this.value;
      const { startNum, endNum, cellNum } = this;
      if (value < startNum) value = startNum;
      if (value > endNum) value = endNum;
      const d_len = (endNum - startNum) / cellNum;
      let defaultInd = 0;
      for (let d = 0; d <= d_len; d++) {
        const item = this.getFixedNum(startNum + d * cellNum);
        if (item === value) {
          defaultInd = d;
          break;
        }
      }
      this.selInd = defaultInd;
      this.slideTo(defaultInd);
    },

    slideTo(ind) {
      const newLeft = ind * this.cellWidth;
      this.scrollLeft = newLeft;
    },

    // ✅ 发射时也保留一位小数
    setEmitFunc() {
      const num = this.getFixedNum(this.selInd * this.cellNum + this.startNum);
      this.$emit('input', num);
      this.$emit('change', num);
    },

    checkValueRange(val) {
      const { startNum, endNum } = this;
      if (val < startNum) {
        this.$emit('input', startNum);
        this.$emit('change', startNum);
        this.getSelInd();
      } else if (val > endNum) {
        this.$emit('input', endNum);
        this.$emit('change', endNum);
        this.getSelInd();
      }
    },
  },
  watch: {
    value(newVal) {
      this.checkValueRange(newVal);
      this.getSelInd();
    },
  },
};
</script>

<style>
/* 隐藏滚动条 */
.ruler-scroll::-webkit-scrollbar {
  display: none;
}
.ruler-scroll {
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.slide-scroll {
  display: flex;
  flex-wrap: nowrap;
  flex-direction: row;
}

.slide-list,
.slide-item {
  flex-shrink: 0;
  position: relative;
  border-radius: 4px;
  transition: all 0.15s ease-out;
}

.list-num {
  position: absolute;
  left: 50%;
  height: 40px;
  transform: translateX(-50%);
}

.empty-none {
  flex-shrink: 0;
  height: 5px;
}
</style>
